package com.yy.smartBI.bizmq;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import com.yy.smartBI.mapper.GenChartMapper;
import com.yy.smartBI.model.entity.GenChart;
import com.yy.smartBI.utils.AIUtils;
import javafx.scene.chart.Chart;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

// 使用@Component注解标记该类为一个组件，让Spring框架能够扫描并将其纳入管理
@Component
// 使用@Slf4j注解生成日志记录器
@Slf4j
public class MyMessageConsumer {
    @Resource
    private GenChartMapper genChartMapper;
    /**
     * 接收消息的方法
     *
     * @param message      接收到的消息内容，是一个字符串类型
     * @param channel      消息所在的通道，可以通过该通道与 RabbitMQ 进行交互，例如手动确认消息、拒绝消息等
     * @param deliveryTag  消息的投递标签，用于唯一标识一条消息
     */
    // 使用@SneakyThrows注解简化异常处理
    @SneakyThrows
    // 使用@RabbitListener注解指定要监听的队列名称为"code_queue"，并设置消息的确认机制为手动确认
    @RabbitListener(queues = {"code_queue"}, ackMode = "MANUAL")
    // @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag是一个方法参数注解,用于从消息头中获取投递标签(deliveryTag),
    // 在RabbitMQ中,每条消息都会被分配一个唯一的投递标签，用于标识该消息在通道中的投递状态和顺序。通过使用@Header(AmqpHeaders.DELIVERY_TAG)注解,可以从消息头中提取出该投递标签,并将其赋值给long deliveryTag参数。
    public void receiveMessage(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        // 使用日志记录器打印接收到的消息内容
        log.info("receiveMessage message = {}", message);
        // 投递标签是一个数字标识,它在消息消费者接收到消息后用于向RabbitMQ确认消息的处理状态。通过将投递标签传递给channel.basicAck(deliveryTag, false)方法,可以告知RabbitMQ该消息已经成功处理,可以进行确认和从队列中删除。
        // 手动确认消息的接收，向RabbitMQ发送确认消息
        //处理消息 调用AI
        //1.解析消息 获取图表id
        try {
            String[] splitOrinMeaasgge = message.split("]]]]]");
            if (!(splitOrinMeaasgge.length == 2)) {
                log.error("原始消息不对 无法解析到图表id");
                throw new IllegalArgumentException("原始消息不对 无法解析到图表id");
            }

            String question = splitOrinMeaasgge[0];
            String chartIdStr = splitOrinMeaasgge[1];
            Long chartId = Long.parseLong(chartIdStr);

            //查表 获得表
            GenChart chart = genChartMapper.selectById(chartId);
            if (chart == null) {
                log.error("ai解析过程中  id查询图表不存在");
                throw new IllegalArgumentException("ai解析过程中  id查询图表不存在");
            }
            //2.调用AI
            QueryWrapper<GenChart> genChartQueryWrapper = new QueryWrapper<>();
            genChartQueryWrapper.eq("id", chartId);
            //调用
            String answer = AIUtils.getAnswer(question);
            String[] split = answer.split("]]]]]");
            if (split.length < 3) {
                chart.setStatus("fail");
                genChartMapper.update(chart, genChartQueryWrapper);
                log.error("AI 回答格式不对 无法获取结败");
                throw new IllegalArgumentException("AI 回答格式不对 无法获取结果");
            }
            chart.setCode(split[1]);
            chart.setAdvice(split[2]);
            chart.setStatus("success");
            //3.更新数据库
            int update = genChartMapper.update(chart, genChartQueryWrapper);
            if (update < 1) {
                log.error("数据库执行出错 更新图表失败");
                throw new IllegalArgumentException("数据库执行出错 更新图表失败");
            }
            // 手动确认消息的接收，向RabbitMQ发送确认消息
            channel.basicAck(deliveryTag, false);
        }catch (Exception e){
            // 手动确认消息的接收，向RabbitMQ发送确认消息
            channel.basicAck(deliveryTag, false);
            log.error("消息处理失败", e);
        }
    }

}
